package com.qiall.omsserver.service.oms;

import com.qiall.bashutil.*;
import ch.ethz.ssh2.Connection;
import com.qiall.common.exception.BusinessException;
import com.qiall.common.exception.ResultCode;
import com.qiall.fileutil.FileInfoUtil;
import com.qiall.omsserver.data.entity.ServerInfo;
import com.qiall.omsserver.data.mapper.ServerInfoMapper;
import  com.qiall.uriutil.HttpUtil;

import com.qiall.omsserver.data.entity.AppCodeInfo;
import com.qiall.omsserver.data.entity.ApplicationInfo;
import com.qiall.omsserver.data.entity.GitBranchInfo;
import com.qiall.omsserver.data.mapper.AppCodeInfoMapper;
import com.qiall.omsserver.data.mapper.ApplicationInfoMapper;
import com.qiall.omsserver.data.mapper.GitBranchMapper;
import com.qiall.omsserver.service.AppOmsService;
import com.qiall.omsserver.service.GitManageService;
import com.qiall.omsserver.service.MavenService;
import com.qiall.omsserver.service.OmsLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.Server;
import org.apache.ibatis.reflection.ExceptionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 默认实现
 */
@Component
@Slf4j
public class DefaultAppOmsServiceImpl implements AppOmsService {

    @Autowired
    private ApplicationInfoMapper applicationInfoMapper;
    @Autowired
    private AppCodeInfoMapper appCodeInfoMapper;

    @Autowired
    private GitBranchMapper gitBranchMapper;
    @Autowired
    private OmsLogService omsLogService;
    @Autowired
    private GitManageService gitManageService;
    @Autowired
    private MavenService mvmPackage;

    @Autowired
    private ServerInfoMapper serverInfoMapper;

    @Override
    public String startApp(Integer appId) {
        //通过 ssh 调用启动命令
        ApplicationInfo applicationInfo = applicationInfoMapper.select(appId);
        String appPath = applicationInfo.getAppPath();
        String startScripPath = appPath + "bin/start.sh";
        try {
           ServerInfo serverInfo= serverInfoMapper.select(applicationInfo.getAppHostId());
            Connection connection = SshScripUtil.login(serverInfo.getServerHost(), serverInfo.getLoginName(), serverInfo.getLoginPassword());
            String result = SshScripUtil.execute(connection, startScripPath);
            omsLogService.omsLog(appId, "start app success message from server is " + result);
            return result;
        } catch (Exception e) {
            omsLogService.omsLog(appId, "start app fail message is " + ExceptionUtil.unwrapThrowable(e));

            throw new BusinessException(ResultCode.SYSTEM_ERROR, e.getMessage());
        }

    }

    @Override
    public String stopApp(Integer appId) {
        ApplicationInfo applicationInfo = applicationInfoMapper.select(appId);
        ServerInfo serverInfo=serverInfoMapper.select(applicationInfo.getAppHostId());
        String host = serverInfo.getServerHost();
        String baseUrl = buildBaseUrl(host);
        baseUrl += "stopApp";
        String ret = HttpUtil.get(baseUrl);
        omsLogService.omsLog(appId, "stop service ret message from server is " + ret);
        return ret;
    }


    @Override
    public void upload(Integer appId) {
        ApplicationInfo applicationInfo = applicationInfoMapper.select(appId);
        AppCodeInfo appCodeInfo = appCodeInfoMapper.selectByAppId(appId);
        ServerInfo serverInfo=serverInfoMapper.select(applicationInfo.getAppHostId());
        String codePath = appCodeInfo.getCodePath();
        String appName = applicationInfo.getAppName();
        String localAppPath = codePath + "/target/" + appName + ".jar";
        String host = serverInfo.getServerHost();
        String userName = serverInfo.getLoginName();
        String path = applicationInfo.getAppPath() + "tmp/";
        String password = serverInfo.getLoginPassword();
        omsLogService.omsLog(appId, "start upload package");
        log.info("start upload file [{}]", localAppPath);
        ScpExecUtil.scpFile(host, userName, password, localAppPath, path);
        omsLogService.omsLog(appId, "upload package success");
        log.info("file upload success [{}] ", localAppPath);


    }


    /**
     * 1 pull 代码
     * 2. 打包代码
     * 3.上传代码到服务器
     * 4.停止远程服务
     * 5.拷贝代码到运行目录
     * 6.重启服务
     *
     * @param appId
     */
    @Override
    public void deploy(Integer appId) {
        //todo 默认只有一个分支后期优化
        //执行事件较长所以新开一个线程
        List<GitBranchInfo> gitBranchInfoList = gitBranchMapper.selectByAppId(appId);
        new Thread(() -> {
            gitManageService.gitPull(appId, gitBranchInfoList.get(0).getId());
            // 打包
            mvmPackage.mvmPackage(appId);
            //上传包
            upload(appId);

            //停止服务 todo
            stopApp(appId);
            //拷贝包到运行目录
            copyPackageToServiceDir(appId);
            //重启服务
            startApp(appId);
            //清除暂存文件
            removeTmpFile(appId);

        }).start();


    }

    private void copyPackageToServiceDir(int appId) {
        //链接远程服务
        ApplicationInfo applicationInfo = applicationInfoMapper.select(appId);
        ServerInfo serverInfo=serverInfoMapper.select(applicationInfo.getAppHostId());
        try {
            Connection connection = SshScripUtil.login(serverInfo.getServerHost(), serverInfo.getLoginPassword(), serverInfo.getLoginPassword());
            String appPath = applicationInfo.getAppPath();
            String appTmpPath = appPath + "/tmp/";
            SshScripUtil.execute(connection, "cp " + appTmpPath + buildAppName(applicationInfo.getAppName()) + " " + appPath + "/" + buildAppName(applicationInfo.getAppName())+" "+appPath+"/");
            omsLogService.omsLog(appId, "copy package to service dir success");
        } catch (Exception e) {
            throw new BusinessException(ResultCode.SYSTEM_ERROR, "连接远程服务器失败");
        }

    }

    private void removeTmpFile(int appId) {
        //链接远程服务
        ApplicationInfo applicationInfo = applicationInfoMapper.select(appId);
        ServerInfo serverInfo=serverInfoMapper.select(applicationInfo.getAppHostId());
        try {
            Connection connection = SshScripUtil.login(serverInfo.getServerHost(), serverInfo.getLoginName(), serverInfo.getLoginPassword());
            String appPath = applicationInfo.getAppPath();
            String appTmpPath = appPath + "/tmp/rm.sh";
            SshScripUtil.execute(connection, appTmpPath);
            omsLogService.omsLog(appId, "remove tmp file from tmp dir success ");
        } catch (Exception e) {
            omsLogService.omsLog(appId, "remove tmp file from tmp dir fail error is "+ExceptionUtil.unwrapThrowable(e));

            throw new BusinessException(ResultCode.SYSTEM_ERROR, "链接远程服务器失败");
        }

    }

    private String buildBaseUrl(String host) {
        String url = "https://";
        url += host;
        url += "/qiall/appManage/";
        return url;
    }

    private String buildAppName(String appName) {
        return appName + ".jar";
    }
}
